;每8k 写成一个 bank
;//mmc3 
;//最后一块PRG芯片占据 0xc000~0xffef 16k两个bank
;//当PRG芯片多于一块时，默认第一块芯片占据8000~BFFF 两个bank
;//其它PRG芯片动态映射，不映射只有32k空间
;//Chr芯片有多片可以切换，默认第一片
  .inesprg 3   ; 2x 16KB PRG code //4 bank? 0 1 2 3?
  .ineschr 1   ; 1x  8KB CHR data
  .inesmap 4  ; mapper 0 = NROM, no bank swapping 4=MMC3
  .inesmir 1   ; background mirroring
  

;;;;;;;;;;;;;;;

    
  .bank 1
  .org $A000
Main:
  SEI          ;  set enable flag I，I flag 打开的时候 代表 中断关闭，这是反着的
  ;CLD          ; disable decimal mode 无意义指令，NES定制CPU根本就没有decimal支持
  LDX #$40 ;#表示立即数 SET X = 0x40
  STX $4017    ; disable APU frame IRQ  mem[0x4017]=x    0x8000~0xffff 是用户内存，其它都是特殊地址，大量使用写地址来完成功能
  LDX #$FF ;SET X=0xff
  TXS          ; Set up stack SET S = X
  ;INX          ; now X = 0 又用溢出技巧清零，这是个奇技淫巧，
  LDX #0	;//我们换成更容易理解的方式
  STX $2000    ; disable NMI  mem[0x2000] = reg_x
  STX $2001    ; disable rendering
  STX $4010    ; disable DMC IRQs

.Main.vblankwait1:       ; First wait for vblank to make sure PPU is ready
 ;{loop
  ;BIT $2002 ;//n v z==a? 
  ;BPL Main.vblankwait1 ;//N的最高位为0 时 回去 这个逻辑表达很不通用，8位机是第7bit负值，这个作为编译器可以优化，但是人表达很烦
  ;必须得知道 BIT 指令的细节
  LDA #%10000000;
  AND $2002;   //判断最高位，如果最高位为1 则 Z=1 ，否则满足BNE
  BNE .Main.vblankwait1 ;多一条指令让逻辑更清晰
;}
Main.clrmem:
;{//8 bit 机器，优化是个尴尬点，纯逻辑隐藏掉偏移的化，这个可能会多出很多变量
 ;//需要保留指令里的偏移，让编译器想办法去
 ;for(var x=0;x<=255;x++)
 ;{
 ;   set mem[0x0000,x] = reg_a
 ;   mem[0x0000+x] = reg_A;
 ;   mem[0x0100+x] = reg_A;
 ;   mem[0x0300+x] = reg_A;
 ;   mem[0x0400+x] = reg_A;
 ;}
  LDA #0
  STA $0000, x;//这个地方,+x 不是无聊代码，x是循环内容，用偏移方式可以优化代码
  STA $0100, x
  STA $0300, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #0
  STA $0200, x    ;move all sprites off screen
  INX
  BNE Main.clrmem;//这里的BNE 是判断 INX==0，X是8bit，超过255 再加一次就是0
  ;//这是个利用溢出的技巧
;}  
Main.vblankwait2:      ; Second wait for vblank, PPU is ready after this
  ;{loop
  	;BIT $2002
  	;BPL Main.vblankwait2
  	 LDA #%10000000;
	 AND $2002;   //判断最高位，如果最高位为1 则 Z=1 ，否则满足BNE
	 BNE Main.vblankwait2 ;多一条指令让逻辑更清晰
  ;}


; ************** NEW CODE ****************
Main.LoadPalettes:
  LDA $2002    ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006    ; write the high byte of $3F00 address
  LDA #0
  STA $2006    ; write the low byte of $3F00 address
  LDX #0	;//set x=0;
  ;{
Main.LoadPalettesLoop:;x循环 32个字节调色板
  LDA palette, x        ;load palette byte
  STA $2007             ;write to PPU
  INX                   ;x++
  CPX #$20            
  BNE Main.LoadPalettesLoop  ;if x = $20, 32 bytes copied, all done
  ;if(x!=32) continue loop
;}

  ;TSX ;//留内存法
  ;TXA
  ;SEC
  ;DEC #8 ;//留8字节内存,完事在ret前再把S 改回去 0x100 ~0x1FF 是栈内存
  ;0x100+s 就是当前栈内存位置
  ;TAX
  ;TXS
  
  LDY #0
  LDA #$08
  PHA   ;//压栈法,处理临时数据有顺序性，可以简单处理少量的数据
  ;8位机留内存法需要写大量代码
Main.LoopSp:

  ;//取内存法 ，取内存法在变量多时不怕
  TSX
  INX;//x++
  LDA $0100,x
  ADC #8
  STA $0100,x
  
  ;//取栈法
  ;PLA;
  ;ADC #8
  ;PHA

  STA $0200,y        ; put sprite 0 in center ($80) of screen vert
  LDA #$70
  STA $0203,y        ; put sprite 0 in center ($80) of screen horiz
  ;LDA #$1d
   TYA;//让title数字浪起来
  STA $0201,y        ; tile number = 0
  LDA #0
  STA $0202,y       ; color = 0, no flipping

  
  TYA 
  ADC #4
  TAY
  
  CPY #$60    
  BNE Main.LoopSp 
 
 PLA;;//压下去的栈要还原

  LDA #%10000000   ; enable NMI, sprites from Pattern Table 0
  STA $2000

  LDA #%00010000   ; enable sprites
  STA $2001

;{
Main.Forever:
  JMP Main.Forever     ;jump back to Forever, infinite loop
	;continue;
;}
 

NMI:
  LDA #$00
  STA $2003  ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014  ; set the high byte (02) of the RAM address, start the transfer
  
  RTI        ; return from interrupt
 
;;;;;;;;;;;;;;  
  
  palette:
  .db $0F,$31,$32,$33,$0F,$35,$36,$37,$0F,$39,$3A,$3B,$0F,$3D,$3E,$0F
  .db $0F,$1C,$15,$14,$0F,$02,$38,$3C,$0F,$1C,$15,$14,$0F,$02,$38,$3C

  
  .bank 5  ;8k E000 ~ FFFF,最后浪费几个控制字节
  
  ;.org $E000


  .org $FFFA     ;first of the three vectors starts here
  .dw NMI        ;when an NMI happens (once per frame if enabled) the 
                   ;processor will jump to the label NMI:
  .dw Main      ;when the processor first turns on or is reset, it will jump
                   ;to the label RESET:
  .dw 0          ;external interrupt IRQ is not used in this tutorial
  
  
;;;;;;;;;;;;;;  
  ;CHR part 
  
  .bank 6
  .org $0000
  .incbin "mario.chr"   ;includes 8KB graphics file from SMB1